using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace MT5Trade.Models.MarketData
{
    /// <summary>
    /// 文件缓存管理器，用于缓存市场数据到本地文件
    /// </summary>
    public class FileDataCache
    {
        private readonly string _cacheDirectory;
        private readonly ILogger<FileDataCache> _logger;
        private readonly TimeSpan _defaultExpiration;

        public FileDataCache(
            string cacheDirectory = null,
            ILogger<FileDataCache> logger = null,
            TimeSpan? defaultExpiration = null)
        {
            _cacheDirectory = cacheDirectory ?? Path.Combine(Directory.GetCurrentDirectory(), "MarketDataCache");
            _logger = logger ?? CreateDefaultLogger();
            _defaultExpiration = defaultExpiration ?? TimeSpan.FromHours(4); // 默认4小时过期

            // 确保缓存目录存在
            if (!Directory.Exists(_cacheDirectory))
            {
                Directory.CreateDirectory(_cacheDirectory);
                _logger.LogInformation($"创建缓存目录: {_cacheDirectory}");
            }
        }

        private static ILogger<FileDataCache> CreateDefaultLogger()
        {
            using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
            return loggerFactory.CreateLogger<FileDataCache>();
        }

        /// <summary>
        /// 获取缓存的历史数据
        /// </summary>
        public async Task<List<MarketTick>> GetCachedHistoricalDataAsync(
            string symbol,
            DateTime startDate,
            DateTime endDate,
            Interval interval = Interval.Daily)
        {
            var cacheKey = GenerateCacheKey(symbol, startDate, endDate, interval);
            var filePath = GetCacheFilePath(cacheKey);

            if (!File.Exists(filePath))
            {
                _logger.LogDebug($"缓存未找到: {cacheKey}");
                return null;
            }

            var fileInfo = new FileInfo(filePath);

            // 检查缓存是否过期
            if (DateTime.UtcNow - fileInfo.LastWriteTimeUtc > _defaultExpiration)
            {
                _logger.LogDebug($"缓存已过期: {cacheKey}");
                // 删除过期文件
                try
                {
                    File.Delete(filePath);
                }
                catch (Exception ex)
                {
                    _logger.LogWarning($"删除过期缓存失败: {ex.Message}");
                }
                return null;
            }

            try
            {
                var json = await File.ReadAllTextAsync(filePath);
                var data = JsonConvert.DeserializeObject<CachedData<List<MarketTick>>>(json);

                _logger.LogInformation($"从缓存加载数据: {symbol}, 记录数: {data.Value?.Count ?? 0}");
                return data.Value;
            }
            catch (Exception ex)
            {
                _logger.LogError($"读取缓存失败: {ex.Message}");
                // 删除损坏的缓存文件
                try
                {
                    File.Delete(filePath);
                }
                catch { }
                return null;
            }
        }

        /// <summary>
        /// 保存历史数据到缓存
        /// </summary>
        public async Task SaveHistoricalDataAsync(
            string symbol,
            DateTime startDate,
            DateTime endDate,
            Interval interval,
            List<MarketTick> data)
        {
            if (data == null || !data.Any())
            {
                _logger.LogWarning($"无数据可缓存: {symbol}");
                return;
            }

            var cacheKey = GenerateCacheKey(symbol, startDate, endDate, interval);
            var filePath = GetCacheFilePath(cacheKey);

            var cachedData = new CachedData<List<MarketTick>>
            {
                Key = cacheKey,
                Value = data,
                CreatedAt = DateTime.UtcNow,
                ExpiresAt = DateTime.UtcNow.Add(_defaultExpiration),
                Symbol = symbol,
                StartDate = startDate,
                EndDate = endDate,
                Interval = interval,
                RecordCount = data.Count
            };

            try
            {
                var json = JsonConvert.SerializeObject(cachedData, Formatting.Indented);
                await File.WriteAllTextAsync(filePath, json);
                _logger.LogInformation($"数据已缓存: {symbol}, 记录数: {data.Count}, 文件: {Path.GetFileName(filePath)}");
            }
            catch (Exception ex)
            {
                _logger.LogError($"保存缓存失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 批量下载并缓存多个品种的数据
        /// </summary>
        public async Task<Dictionary<string, List<MarketTick>>> GetBulkDataWithCacheAsync(
            List<string> symbols,
            DateTime startDate,
            DateTime endDate,
            Func<string, DateTime, DateTime, Task<List<MarketTick>>> fetchFunc,
            Interval interval = Interval.Daily)
        {
            var result = new Dictionary<string, List<MarketTick>>();

            foreach (var symbol in symbols)
            {
                // 首先检查缓存
                var cachedData = await GetCachedHistoricalDataAsync(symbol, startDate, endDate, interval);

                if (cachedData != null)
                {
                    result[symbol] = cachedData;
                    _logger.LogInformation($"使用缓存数据: {symbol}");
                }
                else
                {
                    // 从API获取数据
                    try
                    {
                        _logger.LogInformation($"从API获取数据: {symbol}");
                        var data = await fetchFunc(symbol, startDate, endDate);

                        if (data != null && data.Any())
                        {
                            // 保存到缓存
                            await SaveHistoricalDataAsync(symbol, startDate, endDate, interval, data);
                            result[symbol] = data;
                        }

                        // 添加延迟，避免API限流
                        await Task.Delay(2000);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError($"获取{symbol}数据失败: {ex.Message}");
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 清理过期缓存
        /// </summary>
        public async Task CleanupExpiredCacheAsync()
        {
            await Task.Run(() =>
            {
                try
                {
                    var files = Directory.GetFiles(_cacheDirectory, "*.json");
                    var expiredCount = 0;

                    foreach (var file in files)
                    {
                        var fileInfo = new FileInfo(file);
                        if (DateTime.UtcNow - fileInfo.LastWriteTimeUtc > _defaultExpiration)
                        {
                            try
                            {
                                File.Delete(file);
                                expiredCount++;
                            }
                            catch (Exception ex)
                            {
                                _logger.LogWarning($"删除过期文件失败 {file}: {ex.Message}");
                            }
                        }
                    }

                    if (expiredCount > 0)
                    {
                        _logger.LogInformation($"清理了 {expiredCount} 个过期缓存文件");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"清理缓存失败: {ex.Message}");
                }
            });
        }

        /// <summary>
        /// 获取缓存统计信息
        /// </summary>
        public CacheStatistics GetStatistics()
        {
            var stats = new CacheStatistics
            {
                CacheDirectory = _cacheDirectory,
                TotalFiles = 0,
                TotalSizeBytes = 0,
                ExpiredFiles = 0,
                ActiveFiles = 0
            };

            try
            {
                var files = Directory.GetFiles(_cacheDirectory, "*.json");
                stats.TotalFiles = files.Length;

                foreach (var file in files)
                {
                    var fileInfo = new FileInfo(file);
                    stats.TotalSizeBytes += fileInfo.Length;

                    if (DateTime.UtcNow - fileInfo.LastWriteTimeUtc > _defaultExpiration)
                    {
                        stats.ExpiredFiles++;
                    }
                    else
                    {
                        stats.ActiveFiles++;
                    }
                }

                stats.TotalSizeMB = stats.TotalSizeBytes / (1024.0 * 1024.0);
            }
            catch (Exception ex)
            {
                _logger.LogError($"获取缓存统计失败: {ex.Message}");
            }

            return stats;
        }

        /// <summary>
        /// 预热缓存 - 批量下载常用品种的数据
        /// </summary>
        public async Task WarmupCacheAsync(
            List<string> symbols,
            Func<string, DateTime, DateTime, Task<List<MarketTick>>> fetchFunc,
            int lookbackDays = 30)
        {
            var endDate = DateTime.UtcNow;
            var startDate = endDate.AddDays(-lookbackDays);

            _logger.LogInformation($"开始预热缓存: {symbols.Count} 个品种, {lookbackDays} 天数据");

            var successCount = 0;
            var failureCount = 0;

            foreach (var symbol in symbols)
            {
                try
                {
                    // 检查是否已有缓存
                    var existing = await GetCachedHistoricalDataAsync(symbol, startDate, endDate);
                    if (existing != null)
                    {
                        _logger.LogDebug($"{symbol} 已有缓存，跳过");
                        successCount++;
                        continue;
                    }

                    // 下载并缓存
                    _logger.LogInformation($"下载 {symbol} 数据...");
                    var data = await fetchFunc(symbol, startDate, endDate);

                    if (data != null && data.Any())
                    {
                        await SaveHistoricalDataAsync(symbol, startDate, endDate, Interval.Daily, data);
                        successCount++;
                        _logger.LogInformation($"{symbol} 下载成功: {data.Count} 条记录");
                    }
                    else
                    {
                        failureCount++;
                        _logger.LogWarning($"{symbol} 无数据");
                    }

                    // 延迟避免API限流
                    await Task.Delay(3000);
                }
                catch (Exception ex)
                {
                    failureCount++;
                    _logger.LogError($"{symbol} 下载失败: {ex.Message}");
                }
            }

            _logger.LogInformation($"缓存预热完成: 成功 {successCount}, 失败 {failureCount}");
        }

        private string GenerateCacheKey(string symbol, DateTime startDate, DateTime endDate, Interval interval)
        {
            return $"{symbol}_{startDate:yyyyMMdd}_{endDate:yyyyMMdd}_{interval}";
        }

        private string GetCacheFilePath(string cacheKey)
        {
            return Path.Combine(_cacheDirectory, $"{cacheKey}.json");
        }
    }

    /// <summary>
    /// 缓存数据包装类
    /// </summary>
    public class CachedData<T>
    {
        public string Key { get; set; }
        public T Value { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime ExpiresAt { get; set; }
        public string Symbol { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public Interval Interval { get; set; }
        public int RecordCount { get; set; }
    }

    /// <summary>
    /// 缓存统计信息
    /// </summary>
    public class CacheStatistics
    {
        public string CacheDirectory { get; set; }
        public int TotalFiles { get; set; }
        public int ActiveFiles { get; set; }
        public int ExpiredFiles { get; set; }
        public long TotalSizeBytes { get; set; }
        public double TotalSizeMB { get; set; }
    }
}